今日的程式碼 => GITHUB
這邊我會用到 json_serializable 的套件和 Http 和 Equatable 的套件。這兩個是超級重要的套件,喜歡的話可以在 pub.dev 加到我的最愛呦~
這編我要請求 https://jsonplaceholder.typicode.com/posts/1 這個網址的資料,並顯示在手機上面
dev branch
。而不是支援 flutter 的 meta
版本,所以這邊我是有把版本降下了一些可以參考 教學範例
dependencies:
json_annotation: ^4.0.0
dev_dependencies:
build_runner: ^2.0.0
json_serializable: ^4.0.0
dependencies:
http: ^0.13.3
equatable: ^2.0.3
我們先來看 https://jsonplaceholder.typicode.com/posts/1 的 JSON 樣子是什麼。不清楚什麼是 JSON 的話可以看這裡 => W3School
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
Equatable
是用來讓物件可以等於物件的。詳細可以看 Equatable 套件說明
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
part 'post_model.g.dart';
// 變成 黨名.g.dart
@JsonSerializable()
class PostModel extends Equatable{
final int userId;// json 欄位名稱
final int id;// json 欄位名稱
final String title;// json 欄位名稱
final String body;// json 欄位名稱
PostModel({required this.userId, required this.id, required this.title, required this.body});// required 裡面也要改成
factory PostModel.fromJson(Map<String, dynamic> json) => _$PostModelFromJson(json);
// 這裡的 PostModel.fromJson 的 PostModel 也要改動,後面的 _$PostModelFromJson 的 PostModelFromJson 也要改動
// 變成 XXX.fromJson _$XXXFromJson
Map<String, dynamic> toJson() => _$PostModelToJson(this);
// 這裡的 _$PostModelToJson(this) 的 PostModel 也要改動,變成 _$XXXToJson(this)
@override
String toString() => "$userId $id $title $body";
@override
List<Object?> get props => [userId, id, title, body];
}
這邊超神奇的,我們去終端機吧,下完指令,會產生一個 post_model.g.dart
的檔案
flutter pub run build_runner build
這邊官方文件寫得蠻清楚的 => HTTP
以下是範例的 HTTP 使用部分,裡面的參數 apidata
是一個我在 function 外面宣告的變數
void fetchData() async {
// 請求時間錊多幾秒
const timeout = Duration(seconds: 10);
// URI 需要傳入 String authority, String unencodedPath, [Map<String, dynamic>? queryParameters
var url = Uri.https('jsonplaceholder.typicode.com', '/posts/1',);
// Await the http get response, then decode the json-formatted response.
var response = await http.get(url).timeout(timeout);
// 如果是 response.statusCode 是 200 的話,我們再去解析 Json
if (response.statusCode == 200) {
setState(() {
apidata = PostModel.fromJson(json.decode(response.body));
});
// 如果需要 是 List<PostModel> 的話可以使用下面的方式。
// List<PostModel>.from(json.decode(response.body).map((c) => PostModel.fromJson(c)).toList());
} else {
throw Exception();
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
/// 初始化的資料,之後請求到資料後,存在這裡。
PostModel? apidata;
@override
void initState() {
super.initState();
// 請求資料
fetchData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('API Sample'),
),
body: Center(
child: Text(
apidata == null ? "" : apidata.toString(),
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20),
),
),
);
}
void fetchData() async {
// 請求時間最多幾秒
const timeout = Duration(seconds: 10);
// URI 可以傳入 String authority, String unencodedPath, [Map<String, dynamic>? queryParameters
var url = Uri.https(
'jsonplaceholder.typicode.com',
'/posts/1',
);
// Await the http get response, then decode the json-formatted response.
var response = await http.get(url).timeout(timeout);
// 如果是 response.statusCode 是 200 的話,我們再去解析 Json
if (response.statusCode == 200) {
setState(() {
apidata = PostModel.fromJson(json.decode(response.body));
});
// 如果需要 是 List<PostModel> 的話可以使用下面的方式。
// List<PostModel>.from(json.decode(response.body).map((c) => PostModel.fromJson(c)).toList());
} else {
throw Exception();
}
}
}
這邊是參考 HTTP 套件包,裡面的 Sample Code
var client = http.Client();
try {
var uriResponse = await client.post(Uri.parse('https://example.com/whatsit/create'),
body: {'name': 'doodle', 'color': 'blue'});
print(await client.get(uriResponse.bodyFields['uri']));
} finally {
client.close();
}